//
// LoaderTask.h
//

#ifndef __LOADER_TASK_H__
#define __LOADER_TASK_H__

#include "SevenHeader.h"
#include "DebugFrame.h"

class CLoaderTask : public CDebugFrame
{
	friend class CLoaderTaskQueue;

public:
	INTERNAL_MEMORY_CHECK(SN_LOADER_TASK);

protected:
	class ReferenceObject : public CDebugFrame
	{
	public:
		INTERNAL_MEMORY_CHECK(SN_LOADER_TASK_REFERENCE_OBJECT);

	public:
		ReferenceObject(void) : uReferenceCount(1) { complete = CreateEvent(NULL, TRUE, FALSE, NULL); }
		~ReferenceObject(void) { CloseHandle(complete); }
		UINT IncReference(void) { return ++uReferenceCount; }
		UINT DecReference(void) { return --uReferenceCount; }

		UINT	uReferenceCount;
		HANDLE	complete;
	}*_ref;

public:
	CLoaderTask(void) {
		_ref = dcnew ReferenceObject;
	}
	CLoaderTask(const CLoaderTask &task)
	{
		_ref = task._ref;
		_ref->IncReference();
	}
	virtual ~CLoaderTask(void) {
		if(_ref->DecReference() == 0) {
			dcdelete _ref;
		}
	}
	
	inline bool isCompleted(void) {
		return WaitForSingleObject(_ref->complete, 0) == WAIT_OBJECT_0;
	}
	inline void wait(void) {
		WaitForSingleObject(_ref->complete, INFINITE);
	}
	CLoaderTask &operator=(const CLoaderTask &task)
	{
		if(this == &task) return *this;
		if(_ref->DecReference() == 0) {
			dcdelete _ref;
		}
		_ref = task._ref;
		_ref->IncReference();
		return *this;
	}
	virtual void begin(void) {} ;
};

class CLoaderTaskQueue : public CDebugFrame
{
private:
	CRITICAL_SECTION _cs;
	std::stack<CLoaderTask *> _tasks;
	HANDLE _hQueued;
	HANDLE _hWorker;

private:
	bool execute(void);
	
public:
	INTERNAL_MEMORY_CHECK(SN_LOADER_TASK_QUEUE);

public:
	CLoaderTaskQueue(void);
	~CLoaderTaskQueue(void);

	bool addTask(CLoaderTask *pTask);

	inline bool isCompleted(void) { return WaitForSingleObject(_hQueued, 0) == WAIT_TIMEOUT; }
	inline void pause(void) { if(_hWorker) SuspendThread(_hWorker); }
	inline void resume(void) { if(_hWorker) ResumeThread(_hWorker); }

	void _thread_callback_worker(void);
};

#endif // __LOADER_H__
